package com.xiaoshuidi.cloud.module.member.service.securitycheck;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.module.member.controller.admin.securitycheck.vo.*;
import com.xiaoshuidi.cloud.module.member.convert.securitycheck.SecurityCheckRectificationItemConvert;
import com.xiaoshuidi.cloud.module.member.enums.RectificationItemStatusEnum;
import com.xiaoshuidi.cloud.module.member.enums.SecurityCheckOverdueStatusEnum;
import com.xiaoshuidi.cloud.module.member.mapper.securitycheck.SecurityCheckRectificationItemMapper;
import com.xiaoshuidi.cloud.module.member.pojo.securitycheck.SecurityCheckDO;
import com.xiaoshuidi.cloud.module.member.pojo.securitycheck.SecurityCheckRectificationItemDO;
import com.xiaoshuidi.cloud.module.system.api.user.AdminUserApi;
import com.xiaoshuidi.cloud.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;

import org.springframework.validation.annotation.Validated;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static com.xiaoshuidi.cloud.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.xiaoshuidi.cloud.module.member.enums.ErrorCodeConstants.*;

/**
 * 安全检查整改项 Service 实现类
 *
 * @author hans.zhang
 */
@Slf4j
@Service
@Validated
public class SecurityCheckRectificationItemServiceImpl extends ServiceImpl<SecurityCheckRectificationItemMapper, SecurityCheckRectificationItemDO> implements SecurityCheckRectificationItemService {

    @Resource
    private SecurityCheckRectificationItemMapper securityCheckRectificationItemMapper;
    @Resource
    private SecurityCheckService securityCheckService;
    @Resource
    private AdminUserApi adminUserApi;

    @Override
    public Long createSecurityCheckRectificationItem(SecurityCheckRectificationItemCreateReqVO createReqVO) {
        securityCheckService.myGetById(createReqVO.getSecurityCheckId());
        // 插入
        SecurityCheckRectificationItemDO securityCheckRectificationItem = SecurityCheckRectificationItemConvert.INSTANCE.convert(createReqVO);
        securityCheckRectificationItem.setStatus(RectificationItemStatusEnum.PENDING.getCode());
        securityCheckRectificationItemMapper.insert(securityCheckRectificationItem);
        // 返回
        return securityCheckRectificationItem.getId();
    }

    @Override
    public void updateSecurityCheckRectificationItem(SecurityCheckRectificationItemUpdateReqVO updateReqVO) {
        // 校验存在
        validateSecurityCheckRectificationItemExists(updateReqVO.getId());
        // 更新
        SecurityCheckRectificationItemDO updateObj = SecurityCheckRectificationItemConvert.INSTANCE.convert(updateReqVO);
        securityCheckRectificationItemMapper.updateById(updateObj);
    }

    @Override
    public void deleteSecurityCheckRectificationItem(Long id) {
        // 检查是否已归档
        SecurityCheckRectificationItemDO securityCheckRectificationItemDO = securityCheckRectificationItemMapper.selectById(id);
        if(ObjectUtil.isEmpty(securityCheckRectificationItemDO)){
            throw exception(SECURITY_CHECK_RECTIFICATION_ITEM_NOT_EXISTS);
        }
        SecurityCheckDO securityCheckDO = securityCheckService.myGetById(securityCheckRectificationItemDO.getSecurityCheckId());
        if(securityCheckDO.getIsPlaceOnFile()){
            throw exception(SECURITY_CHECK_IS_PLACE_ON_FILE);
        }
        // 删除
        securityCheckRectificationItemMapper.deleteById(id);
    }

    private void validateSecurityCheckRectificationItemExists(Long id) {
        if (securityCheckRectificationItemMapper.selectById(id) == null) {
            throw exception(SECURITY_CHECK_RECTIFICATION_ITEM_NOT_EXISTS);
        }
    }

    @Override
    public SecurityCheckRectificationItemDO getSecurityCheckRectificationItem(Long id) {
        return securityCheckRectificationItemMapper.selectById(id);
    }

    @Override
    public List<SecurityCheckRectificationItemDO> getSecurityCheckRectificationItemList(Collection<Long> ids) {
        return securityCheckRectificationItemMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<SecurityCheckRectificationItemRespVO> getSecurityCheckRectificationItemPage(Integer pageNo, Integer pageSize, Long securityCheckId) {
        Page<SecurityCheckRectificationItemRespVO> page = securityCheckRectificationItemMapper.page(new Page<>(pageNo, pageSize), securityCheckId);
        page.getRecords().forEach(securityCheckRectificationItemRespVO -> {
            securityCheckRectificationItemRespVO.setStatus(RectificationItemStatusEnum.getDescByCode(Integer.valueOf(securityCheckRectificationItemRespVO.getStatus())));
        });
        return new PageResult<>(page.getRecords(), page.getTotal());
    }

    @Override
    public List<SecurityCheckRectificationItemDO> getSecurityCheckRectificationItemList(SecurityCheckRectificationItemExportReqVO exportReqVO) {
        return securityCheckRectificationItemMapper.selectList(exportReqVO);
    }

    /**
     * 获得整改项隐患图片
     * @param id 整改项id
     * @return
     */
    @Override
    public List<String> getHazardPhoto(Long id) {
        // 查询并校验存在
        SecurityCheckRectificationItemDO securityCheckRectificationItemDO = securityCheckRectificationItemMapper.selectById(id);
        if (ObjectUtil.isEmpty(securityCheckRectificationItemDO)) {
            throw exception(SECURITY_CHECK_RECTIFICATION_ITEM_NOT_EXISTS);
        }
        String hazardPhoto = securityCheckRectificationItemDO.getHazardPhoto();
        List<String> hazardPhotos = new ArrayList<>();
        if(ObjectUtil.isNotEmpty(hazardPhoto)){
            hazardPhotos = Arrays.asList(hazardPhoto.split(","));
        }
        return hazardPhotos;
    }

    /**
     *
     * @param id 获得整改项回复图片
     * @return
     */
    @Override
    public List<String> getReturnPhoto(Long id) {
        // 查询并校验存在
        SecurityCheckRectificationItemDO securityCheckRectificationItemDO = securityCheckRectificationItemMapper.selectById(id);
        if (ObjectUtil.isEmpty(securityCheckRectificationItemDO)) {
            throw exception(SECURITY_CHECK_RECTIFICATION_ITEM_NOT_EXISTS);
        }
        String returnPhoto = securityCheckRectificationItemDO.getReturnPhoto();
        List<String> returnPhotos = new ArrayList<>();
        if(ObjectUtil.isNotEmpty(returnPhoto)){
            returnPhotos = Arrays.asList(returnPhoto.split(","));
        }
        return returnPhotos;
    }

    /**
     * 检查是否存在即将到期/已到期未处理的整改项
     * @param loginUserId 当前登录的用户
     * @return
     */
    @Override
    public Integer CheckForExpiringCorrections(Long loginUserId) {
        LocalDate now = LocalDate.now();
        LocalDate threeDaysLater = now.plusDays(3);
        QueryWrapper<SecurityCheckRectificationItemDO> wrapper = Wrappers.query();
        wrapper.eq("mscri.deleted", false);
        wrapper.eq("mscpg.gridders_id", loginUserId);
        wrapper.eq("msc.is_need_rectification", true);
        wrapper.eq("mscri.status", RectificationItemStatusEnum.PENDING.getCode());
        wrapper.and(wrap -> wrap.le("mscri.timeframe", threeDaysLater)
                .ge("mscri.timeframe", now)
                .or(wr -> wr.lt("mscri.timeframe", now))
        );
        List<SecurityCheckRectificationItemDO> securityCheckRectificationItemDOS = securityCheckRectificationItemMapper.getForExpiringCorrections(wrapper);
        log.info("当前登录用户:{}, 当前时间:{}, 三天后时间:{}, 整改项:{}", loginUserId, now, threeDaysLater, JsonUtils.toJsonString(securityCheckRectificationItemDOS));
        return securityCheckRectificationItemDOS.size();
    }

    /**
     * 隐患台账
     * @param reqVO
     * @return
     */
    @Override
    public PageResult<HazardLedgerPageRespVO> hazardLedger(HazardLedgerPageReqVO reqVO) {
        QueryWrapper<SecurityCheckRectificationItemDO> wrapper = Wrappers.query();
        wrapper.eq("mscri.deleted", false);
        wrapper.between(ObjectUtil.isAllNotEmpty(reqVO.getCheckDateStart(), reqVO.getCheckDateEnd()), "msc.check_date", reqVO.getCheckDateStart(), reqVO.getCheckDateEnd());
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getRectificationStatus()), "mscri.status", reqVO.getRectificationStatus());
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getIsOverdue()), "mscri.is_overdue", reqVO.getIsOverdue());
        wrapper.and(ObjectUtil.isNotEmpty(reqVO.getSearchBox()), wrap -> {
            wrap.like("mscri.wilfulness", reqVO.getSearchBox())
                    .or()
                    .like("mscp.check_work_unit", reqVO.getSearchBox())
                    .or()
                    .like("mscri.responsible_unit", reqVO.getSearchBox())
                    .or()
                    .like("mscp.name", reqVO.getSearchBox());
        });
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getUserId()), "mscpg.gridders_id", reqVO.getUserId());
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getSecurityCheckType()), "msc.security_check_type", reqVO.getSecurityCheckType());
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getStatus()), "mscri.status", reqVO.getStatus());
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getPitfallLevel()), "msc.pitfall_level", reqVO.getPitfallLevel());
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getCheckProgramId()), "mscp.id", reqVO.getCheckProgramId());
        wrapper.orderByAsc("mscri.status");
        wrapper.orderByDesc("mscri.create_time");
        Page<HazardLedgerPageRespVO> page = securityCheckRectificationItemMapper.hazardLedger(new Page<>(reqVO.getPageNo(), reqVO.getPageSize()), wrapper);
//        page.getRecords().forEach( hazardLedgerPageRespVO -> {
//            hazardLedgerPageRespVO.setStatus(RectificationItemStatusEnum.getDescByCode(Integer.valueOf(hazardLedgerPageRespVO.getStatus())));
//        });
        List<Long> wilfulnessIds = page.getRecords().stream().filter(p -> ObjectUtil.isNotEmpty(p.getWilfulness())).map(p -> Long.valueOf(p.getWilfulness())).distinct().collect(Collectors.toList());
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(wilfulnessIds);
        List<HazardLedgerPageRespVO> records = page.getRecords();
        records.forEach( record -> {
            if(ObjectUtil.isNotEmpty(record.getWilfulness())){
                record.setWilfulnessName(userMap.get(Long.valueOf(record.getWilfulness())).getNickname());
            }
        });
        return new PageResult<>(page.getRecords(), page.getTotal());
    }

    /**
     * 隐患台账导出查询数据
     * @param reqVO
     * @return
     */
    @Override
    public List<HazardLedgerPageRespVO> hazardLedgerExport(HazardLedgerExportReqVO reqVO) {
        QueryWrapper<SecurityCheckRectificationItemDO> wrapper = Wrappers.query();
        wrapper.eq("mscri.deleted", false);
        wrapper.between(ObjectUtil.isAllNotEmpty(reqVO.getCheckDateStart(), reqVO.getCheckDateEnd()), "msc.check_date", reqVO.getCheckDateStart(), reqVO.getCheckDateEnd());
        wrapper.eq(ObjectUtil.isNotEmpty(reqVO.getRectificationStatus()), "mscri.status", reqVO.getRectificationStatus());
        wrapper.and(ObjectUtil.isNotEmpty(reqVO.getSearchBox()), wrap -> {
            wrap.like("mscri.wilfulness", reqVO.getSearchBox())
                    .or()
                    .like("mscp.check_work_unit", reqVO.getSearchBox())
                    .or()
                    .like("mscri.responsible_unit", reqVO.getSearchBox());
        });
        List<HazardLedgerPageRespVO> hazardLedgerPageRespVOS = securityCheckRectificationItemMapper.hazardLedgerList(wrapper);
        List<Long> wilfulnessIds = hazardLedgerPageRespVOS.stream().filter(p -> ObjectUtil.isNotEmpty(p.getWilfulness())).map(p -> Long.valueOf(p.getWilfulness())).distinct().collect(Collectors.toList());
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(wilfulnessIds);
        hazardLedgerPageRespVOS.forEach( hazardLedgerPageRespVO -> {
            hazardLedgerPageRespVO.setStatus(RectificationItemStatusEnum.getDescByCode(Integer.valueOf(hazardLedgerPageRespVO.getStatus())));
            if(ObjectUtil.isNotEmpty(hazardLedgerPageRespVO.getWilfulness())){
                hazardLedgerPageRespVO.setWilfulnessName(userMap.get(Long.valueOf(hazardLedgerPageRespVO.getWilfulness())).getNickname());
            }
        });
        return hazardLedgerPageRespVOS;
    }

    /**
     * 当前登录用户负责的整改项
     * @param reqVO
     * @return
     */
    @Override
    public PageResult<HazardLedgerPageRespVO> rectificationItemByUser(HazardLedgerPageReqVO reqVO) {
        return hazardLedger(reqVO);
    }

    /**
     * 整改项详情
     * @param id 整改项id
     * @return
     */
    @Override
    public RectificationItemDetailRespVO rectificationItemDetail(Long id) {
        SecurityCheckRectificationItemDO securityCheckRectificationItemDO = securityCheckRectificationItemMapper.selectById(id);
        if(ObjectUtil.isEmpty(securityCheckRectificationItemDO)){
            throw exception(SECURITY_CHECK_RECTIFICATION_ITEM_NOT_EXISTS);
        }
        SecurityCheckDO securityCheckDO = securityCheckService.myGetById(securityCheckRectificationItemDO.getSecurityCheckId());
        List<String> photos = new ArrayList<>();
        if(ObjectUtil.isNotEmpty(securityCheckRectificationItemDO.getReturnPhoto())){
            photos = Arrays.asList(securityCheckRectificationItemDO.getReturnPhoto().split(","));
        }

        return new RectificationItemDetailRespVO()
                .setInspectorate(securityCheckDO.getInspectorate())
                .setHazardType(securityCheckRectificationItemDO.getHazardType())
                .setIsPlaceOnFile(securityCheckDO.getIsPlaceOnFile())
                .setSecurityCheckType(securityCheckDO.getSecurityCheckType())
                .setPitfallLevel(securityCheckDO.getPitfallLevel())
                .setCheckDate(securityCheckDO.getCheckDate())
                .setIsNeedRectification(securityCheckDO.getIsNeedRectification())
                .setStatus(securityCheckRectificationItemDO.getStatus())
                .setHazardContext(securityCheckRectificationItemDO.getHazardContext())
                .setRemediation(securityCheckRectificationItemDO.getRemediation())
                .setTarget(securityCheckRectificationItemDO.getTarget())
                .setReturnPhoto(photos);
    }

    /**
     * 整改项回复
     * @param reqVO
     * @return
     */
    @Override
    public Boolean rectificationItemReply(RectificationItemReplyReqVO reqVO) {
        SecurityCheckRectificationItemDO securityCheckRectificationItemDO = securityCheckRectificationItemMapper.selectById(reqVO.getId());
        if(ObjectUtil.isEmpty(securityCheckRectificationItemDO)){
            throw exception(SECURITY_CHECK_RECTIFICATION_ITEM_NOT_EXISTS);
        }
        // 检查是否已归档
        securityCheckService.checkIsPlaceOnFile(securityCheckRectificationItemDO.getSecurityCheckId());
        // 更新回复文件和整改项状态
        securityCheckRectificationItemDO.setReturnPhoto(reqVO.getPhotoUrl());
        securityCheckRectificationItemDO.setStatus(RectificationItemStatusEnum.COMPLETED.getCode());
        securityCheckRectificationItemDO.setIsOverdue(SecurityCheckOverdueStatusEnum.NOT_OVERDUE.getValue());
        securityCheckRectificationItemMapper.updateById(securityCheckRectificationItemDO);
        return Boolean.TRUE;
    }


}
